import { checkActor, getMaster, randomMoveInRange } from "../utils/mirUtil";
import { getDistance } from "../utils/utls";
import { getMonItemManage, getSkillId, getSkillName } from "../系统功能/GlobalObjectManage";
import { Minute } from "../配置/基础配置";
import { DamageChangeData } from "./DamageManage";


//10秒没有攻击 就可以切换物品归属
const HinterChangeTime = 10000;
//aniNpc最小执行间隔
const minAniNpcTime = 1500;
class PlayDamageData {
    damage: number = 0;
    lastAttackTime: number = 0;
}


export interface OnFreshLis {
    (Envir: TEnvirnoment, Actor: TActor): void;
}

export interface OnRemoveBuff {
    (Actor: TActor, Buff: TBuff): void;
}

export class SpecialMonManage {
    //特殊怪物map
    specialMonMap: Map<string, any>;
    //启用仇恨系统的列表
    hatredMap: Map<string, any>;
    //启用自定义物品归属系统的列表
    expHinterMap: Map<string, any>;
    //怪物技能设置
    monSkillSet: Map<string, Array<any>>;
    //怪物攻击触发
    onAttackLis: Map<string, Function>;
    //怪物被攻击触发
    onStruckLis: Map<string, Function>;
    //怪物刷新触发
    onFreshLis: Map<string, OnFreshLis>;
    //怪物额外属性
    addAbility: Map<string, Array<any>>;
    //怪物移除buff触发
    onRemoveBuffLis: Map<string, OnRemoveBuff>;

    //怪物使用技能数据
    monSkillData: Map<number, Map<number, number>>;
    //怪物使用ainpc数据
    monAniNpcData: Map<number, number>;
    //怪物仇恨数据
    monHatredData: Map<number, Map<number, PlayDamageData>>;
    //怪物缓存的数据
    monCacheData: Map<number, any>;



    constructor(specialMonSkillSet: Array<any>) {
        this.specialMonMap = new Map<string, any>();
        this.monSkillData = new Map<number, Map<number, number>>();
        this.monHatredData = new Map<number, Map<number, PlayDamageData>>()
        this.monAniNpcData = new Map<number, number>()
        this.monCacheData = new Map<number, any>()


        this.hatredMap = new Map<string, any>()
        this.expHinterMap = new Map<string, any>()
        this.monSkillSet = new Map<string, Array<any>>();
        this.addAbility = new Map<string, Array<any>>();

        this.onAttackLis = new Map<string, Function>();
        this.onStruckLis = new Map<string, Function>();
        this.onFreshLis = new Map<string, OnFreshLis>();
        this.onRemoveBuffLis = new Map<string, OnRemoveBuff>();

        let fuc = (name, item) => {
            this.specialMonMap.set(name, item)

            if (item.skillList && item.skillList.length > 0) {
                this.monSkillSet.set(name, item.skillList);
            }

            if (item.isExpHinter) {
                this.expHinterMap.set(name, item);
            }

            if (item.isHatred) {
                this.hatredMap.set(name, item);
            }

            if (item.onAttack) {
                this.onAttackLis.set(name, item.onAttack);
            }

            if (item.onStruct) {
                this.onStruckLis.set(name, item.onStruct);
            }

            if (item.onFresh) {
                this.onFreshLis.set(name, item.onFresh as OnFreshLis);
            }

            if (item.addAbility) {
                this.addAbility.set(name, item.addAbility);
            }

            if (item.onRemoveBuff) {
                this.onRemoveBuffLis.set(name, item.onRemoveBuff as OnRemoveBuff);
            }
        }

        for (let i = 0; i < specialMonSkillSet.length; i++) {
            let item = specialMonSkillSet[i];

            if (item.skillList && item.skillList.length > 0) {
                for (let i = 0; i < item.skillList.length; i++) {
                    let skillItem = item.skillList[i];
                    if (!skillItem.skillId) {
                        skillItem.skillId = getSkillId(skillItem.skillName)
                    }
                }
            }

            let name = item.name;
            if (name) {
                if (typeof name === "string") {
                    fuc(name, item)
                }
                else if (Array.isArray(name)) {
                    let array = name as Array<String>;
                    for (let i = 0; i < array.length; i++) {
                        let namei = array[i]
                        fuc(namei, item)
                    }
                }
            }

        }
    }

    //怪物攻击触发
    onMonAttack(ActorObject: TActor, ADamageSource: TActor, Tag: number, SkillID: number, SkillLevel: number,
        Value: number): Array<DamageChangeData> {
        if (ADamageSource && !ADamageSource.IsPlayer()) {

            if (this.onAttackLis.has(ADamageSource.Name)) {
                let fuc = this.onAttackLis.get(ADamageSource.Name);
                return fuc(ActorObject, ADamageSource, Tag, SkillID, SkillLevel)
            }
        }
        return null;
    }

    //怪物被攻击触发
    onMonStruck(ActorObject: TActor, ADamageSource: TActor, Tag: number, SkillID: number, SkillLevel: number,
        Value: number): Array<DamageChangeData> {
        if (ActorObject && !ActorObject.IsPlayer()) {
            if (this.onStruckLis.has(ActorObject.Name)) {
                let fuc = this.onStruckLis.get(ActorObject.Name);
                return fuc(ActorObject, ADamageSource, Tag, SkillID, SkillLevel)
            }
        }
        return null;
    }


    //怪物刷新触发
    onMonFresh(Envir: TEnvirnoment, Actor: TActor): void {
        if (checkActor(Actor)) {
            if (this.onFreshLis.has(Actor.Name)) {
                let fuc: OnFreshLis = this.onFreshLis.get(Actor.Name);
                return fuc(Envir, Actor)
            }
        }
    }



    //怪物最终受到伤害触发
    onMonDamage(boss: TActor, source: TActor, Value: number): void {
        if (checkActor(boss) && !boss.IsPlayer() && checkActor(source)) {
            //记录怪物归属
            getMonItemManage().onMonDamage(boss, source, Value);

            let play: TActor = getMaster(source);
            //BOSS和玩家都存活
            let isHatred = this.hatredMap.has(boss.Name);
            // let isExpHinter = this.expHinterMap.has(boss.Name);

            if (isHatred) {
                //计算伤害
                let bossData: Map<number, PlayDamageData>;
                if (this.monHatredData.has(boss.Handle)) {
                    bossData = this.monHatredData.get(boss.Handle)
                }
                else {
                    bossData = new Map<number, PlayDamageData>();
                    this.monHatredData.set(boss.Handle, bossData);
                }

                let playData: PlayDamageData = null;
                if (bossData.has(play.Handle)) {
                    playData = bossData.get(play.Handle);
                }
                else {
                    playData = new PlayDamageData();
                    bossData.set(play.Handle, playData);
                }

                //更新当前攻击人的数据
                let current = GameLib.GetTickCount();
                if (current - playData.lastAttackTime > Minute) {
                    playData.damage = Value;
                }
                else {
                    playData.damage += Value;
                }
                playData.lastAttackTime = current;



                //物品归属判断
                // if (isExpHinter) {
                //     this.monExpHinter(boss, play, Value, bossData);
                // }

                //仇恨值系统
                // if(isHatred)
                // {
                //     this.monHatred(boss,play,source,bossData,playData)
                // }
            }


        }
    }


    //仇恨值系统
    //play 为攻击目标的主人
    monHatred(boss: TActor, play: TActor, source: TActor, bossData: Map<number, PlayDamageData>, playData: PlayDamageData): void {
        // let current=GameLib.GetTickCount();
        // //BOSS当前攻击目标
        // let target:TActor=boss.GetTargetActor();
        // let flag=false;


        // //如果没有目标或者目标已经死亡 则切换目标
        // if(!target||target.Death||target.Master)
        // {
        //     flag=true;
        // }
        // else {  

        //     let dis=getDistance(target,boss);

        //     //boss和目标距离超过10
        //     if(dis>10)
        //     {
        //         flag=true;
        //     }
        //     //目标没有造成伤害 
        //     else if(!bossData.has(target.Handle)){
        //         flag=true;
        //     }
        //     else{
        //         let targetData=bossData.get(target.Handle)
        //         let time=current-targetData.lastAttackTime;
        //         //目标1分钟没有造成伤害 或者伤害小于当前攻击人
        //         if(time>Minute||playData.damage>targetData.damage)
        //         {
        //             flag=true;
        //         }
        //     }
        // }

        // if(flag)
        // {   
        //     //boss和玩家在同一个地图
        //     if(boss.Map.MapID==play.Map.MapID)
        //     {
        //         let dis=getDistance(boss,play);
        //         if(dis>=10)
        //         {
        //             boss.Move(play.Map.MapID, play.MapX,play.MapY);
        //         }
        //         boss.SetTargetActor(play);

        //     }

        // }
    }

    //物品归属判断
    //play 为攻击目标的主人
    monExpHinter(boss: TActor, play: TActor, Value: number, bossData: Map<number, PlayDamageData>): void {
        let expHinter: TActor = boss.GetExpHitter();
        let flag = true;
        if (expHinter) {
            let hinterData: PlayDamageData = bossData.get(expHinter.Handle);
            if (hinterData) {
                let time = GameLib.GetTickCount() - hinterData.lastAttackTime;
                if (time <= HinterChangeTime) {
                    flag = false;
                }
            }
        }
        //确认切换
        if (flag) {
            boss.SetExpHitter(play);
        }
    }
    //获取下次释放的技能
    getNextSkill(Mon: TActor): number {
        let handle = Mon.GetHandle();
        let skillList = this.monSkillSet.get(Mon.Name);

        if (skillList && skillList.length > 0) {
            for (let i = 0; i < skillList.length; i++) {
                let item = skillList[i];

                let percentHp = Mon.HP / Mon.MaxHP;
                if (item.hplarge) {
                    if (percentHp < item.hplarge) {
                        continue;
                    }
                }
                if (item.hpless) {
                    if (percentHp > item.hpless) {
                        continue;
                    }
                }

                //判断目标范围内怪物数量
                // if(item.range&&item.monNum)
                // {
                //     let targetList:TActorList=ATarget.Map.GetActorListAt(ATarget.MapX,ATarget.MapY);
                //     let count=0;
                //     for(let j=0;j<targetList.Count;j++)
                //     {
                //         let targetItem=targetList.Actor(i)
                //         if(!Mon.IsFriendlyTarget(targetItem))
                //         {
                //             count++;
                //         }
                //     }
                //     targetList.Free();
                //     if(count<item.monNum)
                //     {
                //         continue
                //     }
                // }

                let cd = this.getMonSkillData(handle, item.skillId);
                if (cd < item.CD) {
                    continue;
                }
                //检查是否满足使用条件
                if (item.condition) {
                    let flag = item.condition(Mon);
                    if (!flag) {
                        continue;
                    }
                }

                this.setMonSkillData(handle, item.skillId);

                return item.skillId;

            }
        }

        return 0;
    }

    onAINpc(Mon: TActor) {
        // if(!Mon||Mon.Death){
        //     return;
        // }
        // let time=this.monAniNpcData.get(Mon.Handle)||0;
        // let now=GameLib.TickCount
        // if(now-time<minAniNpcTime)
        // {
        //     return;
        // }
        // this.monAniNpcData.set(Mon.Handle,now)

        // let skillId=this.getNextSkill(Mon);
        // let skillName=getSkillName(skillId);
        // if(skillName)
        // {


        //     let isHatred=this.hatredMap.has(Mon.Name);
        //     if(isHatred)
        //     {
        //         let bossData:Map<number,PlayDamageData>=this.monHatredData.get(Mon.Handle)
        //         let getDamage=(play:TPlayObject)=>{
        //             if(bossData)
        //             {
        //                 if(bossData.has(play.Handle))
        //                 {
        //                     let playData:PlayDamageData=bossData.get(play.Handle)
        //                     return playData.damage||0;
        //                 }
        //             }

        //             return 0
        //         }
        //         let play:TPlayObject=null;
        //         let damage=0;
        //         let dis=10000;
        //         let map:TEnvirnoment;
        //         let mapx:number;
        //         let mapy:number;
        //         for(let i=0;i<GameLib.PlayCount;i++)
        //         {
        //             let tmpPlay=GameLib.GetPlayer(i);
        //             //隐身模式的玩家不被攻击
        //             if(tmpPlay.GetObserverMode())
        //             {
        //                 continue;
        //             }
        //             let tmpMap:TEnvirnoment=tmpPlay.Map
        //             let tmpX:number=tmpPlay.MapX
        //             let tmpY:number=tmpPlay.MapY
        //             let distance=getDistance(Mon,tmpPlay);
        //             if(distance>8)
        //             {
        //                 continue;
        //             }
        //             let tmpDamage=getDamage(tmpPlay);
        //             let flag=false;
        //             if(!play)
        //             {
        //                 flag=true;
        //             }
        //             else{
        //                 if(tmpDamage>damage)
        //                 {
        //                     flag=true;
        //                 }
        //                 else if(tmpDamage==damage&&dis>distance)
        //                 {
        //                     flag=true;
        //                 }
        //             }
        //             if(flag)
        //             {
        //                 play=tmpPlay;
        //                 damage=tmpDamage;
        //                 dis=distance;
        //                 map=tmpMap;
        //                 mapx=tmpX
        //                 mapy=tmpY
        //             }
        //         }


        //         if(play)
        //         {
        //             Mon.SetTargetActor(play);
        //             Mon.MagicAttack(play,skillId,false)

        //             if(dis>=3)
        //             {
        //                 // let random:number=randomInRange(3);
        //                 //几率瞬移
        //                 // if(random===0)
        //                 // {
        //                 //     randomMoveInRange(Mon,map,mapx,mapy,3);
        //                 // }
        //                 // else{
        //                     Mon.MoveTo(play.MapX,play.MapY,3);
        //                 // }

        //             }
        //         }
        //         else{
        //             if(Mon.GetTargetActor())
        //             {
        //                 Mon.MagicAttack(Mon.GetTargetActor(),skillId,false)
        //             }
        //         }
        //     }
        //     else{
        //         if(Mon.GetTargetActor())
        //         {
        //             Mon.MagicAttack(Mon.GetTargetActor(),skillId,false)
        //         }
        //     }

        // }

    }

    //怪物使用技能
    onMonSelectMagic(Mon: TActor, ATarget: TActor, AMagicID: number): number {
        if (!checkActor(Mon)) {
            return AMagicID;
        }

        let set = this.getSpecialMonSet(Mon.Name);
        if (set && set.TriggerSelectMagicBeforeAttack == true) {
            let skillId = this.getNextSkill(Mon);


            let isHatred = this.hatredMap.has(Mon.Name);
            if (isHatred) {
                let bossData: Map<number, PlayDamageData> = this.monHatredData.get(Mon.Handle)
                let getDamage = (play: TPlayObject) => {
                    if (bossData) {
                        if (bossData.has(play.Handle)) {
                            let playData: PlayDamageData = bossData.get(play.Handle)
                            return playData.damage || 0;
                        }
                    }

                    return 0
                }
                let play: TPlayObject = null;
                let damage = 0;
                let dis = 10000;
                let map: TEnvirnoment;
                let mapx: number;
                let mapy: number;
                for (let i = 0; i < GameLib.PlayCount; i++) {
                    let tmpPlay = GameLib.GetPlayer(i);
                    //隐身模式的玩家不被攻击
                    if (tmpPlay.GetObserverMode()) {
                        continue;
                    }
                    let tmpMap: TEnvirnoment = tmpPlay.Map
                    let tmpX: number = tmpPlay.MapX
                    let tmpY: number = tmpPlay.MapY
                    let distance = getDistance(Mon, tmpPlay);
                    if (distance > 8) {
                        continue;
                    }
                    let tmpDamage = getDamage(tmpPlay);
                    let flag = false;
                    if (!play) {
                        flag = true;
                    }
                    else {
                        if (tmpDamage > damage) {
                            flag = true;
                        }
                        else if (tmpDamage == damage && dis > distance) {
                            flag = true;
                        }
                    }
                    if (flag) {
                        play = tmpPlay;
                        damage = tmpDamage;
                        dis = distance;
                        map = tmpMap;
                        mapx = tmpX
                        mapy = tmpY
                    }
                }

                if (play) {
                    // Mon.SetTargetActor(play);
                    // if (skillId > 0) {
                    //     // console.log(skillId)
                    //     Mon.MagicAttack(play, skillId, false)
                    // }

                    Mon.SetTargetActorEx(play, 200000)

                    // if (dis >= 3) {
                    //     Mon.MoveTo(play.MapX, play.MapY, 3);
                    // }
                }
                // else {
                //     if (Mon.GetTargetActor() && skillId > 0) {
                //         Mon.MagicAttack(Mon.GetTargetActor(), skillId, false)
                //     }
                // }

                // return 0
            }
            return skillId;


        }
        return AMagicID
    }

    //获取怪物上次使用技能到现在的差值
    getMonSkillData(handle: number, skill: number): number {
        let time = GameLib.GetTickCount();
        let map = null;
        if (this.monSkillData.has(handle) == false) {
            map = new Map<number, number>();
            this.monSkillData.set(handle, map)
            return time;
        }
        else {
            map = this.monSkillData.get(handle);
        }
        let lastTime = map.get(skill) || 0;
        return time - lastTime;
    }

    //怪物使用技能记录数据
    setMonSkillData(handle: number, skill: number): void {
        let map
        if (this.monSkillData.has(handle) == false) {
            map = new Map<number, number>();
            this.monSkillData.set(handle, map)
        }
        else {
            map = this.monSkillData.get(handle);
        }
        map.set(skill, GameLib.GetTickCount());
    }

    //怪物死亡
    onMonDie(Envir: TEnvirnoment, ActorObject: TActor, Killer: TActor, Tag: number) {
        if (ActorObject && !ActorObject.IsPlayer()) {
            let handle = ActorObject.Handle;
            this.monSkillData.delete(handle)
            this.monHatredData.delete(handle)
            this.monAniNpcData.delete(handle)
            this.monCacheData.delete(handle)
        }
    }

    //获取特殊怪物设置
    getSpecialMonSet(monName: string): any {
        if (this.specialMonMap.has(monName)) {
            return this.specialMonMap.get(monName)
        }
        return null
    }

    //获取特殊怪物额外属性
    getSpecialAddAbility(monName: string): Array<any> {
        if (this.addAbility.has(monName)) {
            return this.addAbility.get(monName)
        }
        return null
    }

    onMonSaveData(Actor: TActor, obj: any) {

    }

    onMongGetData(Actor: TActor): any {

    }

    onMonDelData(Actor: TActor): void {
        if (Actor && !Actor.IsPlayer()) {
            let handle = Actor.Handle;
            this.monCacheData.delete(handle)
        }
    }

    //怪物移除BUFF触发
    onRemoveBuff(Actor: TActor, Buff: TBuff): void {
        if (checkActor(Actor) && !Actor.IsPlayer()) {
            if (this.onRemoveBuffLis.has(Actor.Name)) {
                let fuc: OnRemoveBuff = this.onRemoveBuffLis.get(Actor.Name);
                return fuc(Actor, Buff)
            }
        }
    }
}